#include "XgBitmap.h"

unsigned int AlphaBlend(const unsigned int bg, const unsigned int src)
{
	unsigned int a = src >> 24; /* alpha */

	// if alpha is zero, return the background color
	if (0 == a)
		return bg;

	// alpha blending the source and background colors
	unsigned int rb = (((src & 0x00ff00ff) * a) +
		((bg & 0x00ff00ff) * (0xff - a))) & 0xff00ff00;
	unsigned int g = (((src & 0x0000ff00) * a) +
		((bg & 0x0000ff00) * (0xff - a))) & 0x00ff0000;

	return (src & 0xff000000) | ((rb | g) >> 8);
}

XgBitmap::XgBitmap(void)
{
	_hBitmap = NULL;
}

XgBitmap::~XgBitmap(void)
{
}

bool XgBitmap::attach( HMODULE hMod, UINT resourceId )
{
	HANDLE hBitmap = LoadImage( hMod, MAKEINTRESOURCE(resourceId), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );

	if(hBitmap == NULL)
	{
		return false;
	}

	return attach(hBitmap);
}

bool XgBitmap::attach( HANDLE hBitmap )
{
	_hBitmap = hBitmap;
	if( !GetObject( _hBitmap, sizeof(DIBSECTION), &_dibSection ) )
	{
		DeleteObject( _hBitmap );
	}

	return isValid();
}

bool XgBitmap::isValid()
{
	return _hBitmap != NULL;
}

int XgBitmap::width()
{
	if( !isValid())
		return 0;

	return _dibSection.dsBmih.biWidth;
}

int XgBitmap::height()
{
	if( !isValid())
		return 0;

	return _dibSection.dsBmih.biHeight;
}

bool XgBitmap::paint( HDC dc, ULONG dstX, ULONG dstY, ULONG srcX, ULONG srcY, ULONG srcW /*= 0*/, ULONG srcH /*= 0*/)
{
	RECT dstRect;
	RECT srcRect;

	if( srcW == 0 )
	{
		srcW = width() - srcX;
	}

	if( srcH == 0 )
	{
		srcH = height() - srcY;
	}

	dstRect.left = dstX;
	dstRect.top = dstY;
	dstRect.right = dstRect.left + srcW;
	dstRect.bottom = dstRect.top + srcH;

	srcRect.left = srcX;
	srcRect.top = srcY;
	srcRect.right = srcRect.left + srcW;
	srcRect.bottom = srcRect.top + srcH;

	return paint( dc, &dstRect, &srcRect );
}

bool XgBitmap::paint( HDC dc, LPRECT lpDstRect /*= 0*/, LPRECT lpSrcRect /*= 0*/)
{
	RECT defDstRect;
	RECT defSrcRect;

	if( lpDstRect == 0 )
	{
		defDstRect.left = 0;
		defDstRect.top = 0;
		defDstRect.right = defDstRect.left + width();
		defDstRect.bottom = defDstRect.top + height();
		lpDstRect = &defDstRect;
	}

	if( lpSrcRect == 0)
	{
		defSrcRect.left = 0;
		defSrcRect.top = 0;
		defSrcRect.right = defDstRect.left + width();
		defSrcRect.bottom = defDstRect.top + height();
		lpSrcRect = &defSrcRect;
	}

	int r = SetDIBitsToDevice(dc,
		lpDstRect->left, lpDstRect->top,
		lpSrcRect->right - lpSrcRect->left, lpSrcRect->bottom - lpSrcRect->top,
		lpSrcRect->left, lpSrcRect->top,
		lpSrcRect->top, lpSrcRect->bottom - lpSrcRect->top,
		_dibSection.dsBm.bmBits,
		(BITMAPINFO*)&_dibSection.dsBmih,
		DIB_RGB_COLORS);

	if( r == 0 )
		return false;

	return true;
}

bool XgBitmap::paintMasked( HDC dc, HMODULE hMod, UINT resourceId )
{
	if(!isValid())
	{
		return false;
	}

	HANDLE hMaskBitmap = LoadImage( hMod, MAKEINTRESOURCE(resourceId), IMAGE_BITMAP, 0, 0, LR_MONOCHROME );
	if( !hMaskBitmap )
		return false;

	bool r = paintMasked( dc, (HBITMAP)hMaskBitmap );
	DeleteObject(hMaskBitmap);
	return r;
}

bool XgBitmap::paintMasked( HDC dc, HBITMAP hbmMask )
{
	if(!isValid())
	{
		return false;
	}

	HDC hdcMem = CreateCompatibleDC(dc);
	HBITMAP bmp = CreateCompatibleBitmap(dc, width(), height());
	SelectObject(hdcMem, bmp);
	paint(hdcMem);

	HDC hdcMemMask = CreateCompatibleDC(dc);
	SelectObject(hdcMemMask, hbmMask);

	BitBlt( hdcMem, 0, 0, width(), height(), hdcMemMask, 0, 0, SRCINVERT );
	BitBlt( dc, 0, 0, width(), height(), hdcMemMask, 0, 0, SRCAND );
	BitBlt( dc, 0, 0, width(), height(), hdcMem, 0, 0, SRCPAINT );

	DeleteDC(hdcMem);
	DeleteDC(hdcMemMask);

	return true;
}

bool XgBitmap::paintAlpha( HDC dc, UINT alpha )
{
	if(!isValid())
	{
		return false;
	}

	HDC dstDC = CreateCompatibleDC(dc);
	HBITMAP dstBitmap = CreateCompatibleBitmap(dc, width(), height());
	SelectObject(dstDC, dstBitmap);

	BitBlt(dstDC, 0, 0, width(), height(), dc, 0, 0, SRCCOPY);

	HDC srcDC = CreateCompatibleDC(dc);
	HBITMAP srcBitmap = CreateCompatibleBitmap(dc, width(), height());
	SelectObject(srcDC, srcBitmap);
	paint(srcDC);

	COLORREF srcPixel;
	COLORREF dstPixel;
	COLORREF resPixel;

	for( int y = 0; y < height(); y++ )
	{
		for( int x = 0; x < width(); x++ )
		{
			srcPixel = GetPixel(srcDC, x, y);
			dstPixel = GetPixel(dstDC, x, y);

			srcPixel = srcPixel | (alpha << 24);
			resPixel = AlphaBlend(dstPixel, srcPixel) & 0x00FFFFFF;

			SetPixel( dstDC, x, y, resPixel );
		}
	}

	BitBlt(dc, 0, 0, width(), height(), dstDC, 0, 0, SRCCOPY);

	return true;

}